package jpa4azure.impl;

import static com.windowsazure.samples.table.Filter.And;
import static com.windowsazure.samples.table.Filter.Equal;
import static com.windowsazure.samples.table.Filter.GreaterThanOrEqual;
import static com.windowsazure.samples.table.Filter.LessOrEqual;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.persistence.TypedQuery;

import jpa4azure.type.TypeWrapper;
import jpa4azure.type.TypeWrapperFactory;
import jpa4azure.util.DateUtil;

import com.windowsazure.samples.table.AzureTableEntity;
import com.windowsazure.samples.table.AzureTableEntityCollection;
import com.windowsazure.samples.table.AzureTableManager;
import com.windowsazure.samples.table.Filter;
import com.windowsazure.samples.table.IllegalFilterOperandType;

public class TimestampKeyQuery<T> extends CriteriaQueryAdaptor<T> implements TimestampQueryable<T> {

	TimestampKey key;
	Date from = new Date(0);
	Date to = new Date(Long.MAX_VALUE);
	AzureTableManager client;
	Class<T> c;
	int limit = 1000;

	public TimestampKeyQuery(Class<T> c, TimestampKey timestampKey) {
		key = timestampKey;
		this.c = c;
	}

	public TimestampKeyQuery<T> since(Date a) {
		from = a;
		return this;
	}

	public TimestampKeyQuery<T> before(Date a) {
		to = a;
		return this;
	}

	public TimestampKeyQuery<T> between(Date a, Date a2) {
		from = a;
		to = a2;
		return this;
	}

	public TimestampKeyQuery<T> take(int i) {
		this.limit = i;
		return this;
	}

	@Override
	public TypedQuery<T> getTypedQuery(final AzureEntityManager aem) {
		final TypeWrapper type = TypeWrapperFactory.wrap(c);
		this.client = aem.getTableStorageClient();

		return new TypedQueryAdaptor<T>() {
			public List<T> getResultList() {
				List<T> list = new ArrayList<T>();
				AzureTableEntityCollection results = client.queryEntities(
						type.getTableName(), query(), limit);
				for (AzureTableEntity e : results)
					list.add((T) aem.convert(e));
				return list;
			}

			private Filter query() {
				String since = DateUtil.asKey(from);
				String before = DateUtil.asKey(to);
				try {
					Filter lt = LessOrEqual("RowKey", since);
					Filter gt = GreaterThanOrEqual("RowKey", before);
					Filter partition = Equal("PartitionKey", key.getPartition());
					return And(partition, And(lt, gt));
				} catch (IllegalFilterOperandType e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				return null;
			}

		};
	}

}
